﻿/*
Copyright (C) 2010 INOUE Hiroyuki

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CodePlex.Dombly.DiskUsage.BusinessLogic
{
    /// <summary>
    /// Provides information of snapshots.
    /// </summary>
    public class SnapShot : ISnapShot, IDisposable
    {
        #region properties

        #region Id
        /// <summary>
        /// Gets the unique identifier of the instance.
        /// </summary>
        public Guid Id { get { return this._Id; } }
        private readonly Guid _Id;
        #endregion

        #region Name
        /// <summary>
        /// Gets the user-friendly name of the snapshot.
        /// </summary>
        public string Name { get { return this._Name; } }
        private readonly string _Name;
        #endregion

        #region StartTime
        /// <summary>
        /// Gets the time when the snapshot begins.
        /// </summary>
        public DateTime StartTime { get; private set; }
        #endregion

        #region FinishTime
        /// <summary>
        /// Gets the time when the snapshot is completed.
        /// </summary>
        public DateTime? FinishTime { get; private set; }
        #endregion

        #region IsPersistent
        /// <summary>
        /// Gets a value indicating whether the snapshot is persistent.
        /// </summary>
        public bool IsPersistent { get; set; }
        #endregion

        #region Status
        /// <summary>Gets the status of the snapshot.</summary>
        public Statuses Status { get; private set; }
        #endregion

        #region (static)Current
        /// <summary>Gets current snapshot session.</summary>
        public static SnapShot Current
        { get { return _Current = _Current ?? new SnapShot(); } }
        private static SnapShot _Current;
        #endregion

        #region (static)PersistAction
        /// <summary>
        /// An action to perpetuate a snapshot.
        /// </summary>
        public static Action<SnapShot> PerpetuateAction;
        #endregion

        #endregion

        #region constructors
        
        /// <summary>
        /// Initializes a copied instance of SnapShot class from a source object.
        /// </summary>
        /// <param name="source">Source object.</param>
        public SnapShot(ISnapShot source)
        {
            this._Id = source.Id;
            this._Name = source.Name;
            this.StartTime = source.StartTime;
            this.FinishTime = source.FinishTime;
            this.Status = source.Status;
        }

        /// <summary>
        /// Initializes a new instance of SnapShot class.
        /// </summary>
        private SnapShot()
        {
            this._Id = new Guid();
            this.StartTime = DateTime.Now;
            this.Status = Statuses.Running;
            //If the perpetuating action is set, call it.
            if (PerpetuateAction != null)
            {
                this.IsPersistent = true;
                PerpetuateAction(this);
            }
        }

        #endregion

        #region methods
        /// <summary>
        /// Finish current snapshot session.
        /// </summary>
        public static void Finish()
        {
            if (_Current == null)
            {
                throw new InvalidOperationException(
                    "No snapshot session has been started yet.");
            }

            if (_Current.IsPersistent)
            {
                _Current.FinishTime = DateTime.Now;
                _Current.Status = Statuses.Finished;
                _Current.Dispose();
            }
            _Current = null;
        }
        #endregion

        #region IDisposable members

        /// <summary>
        /// Perpetuate the result of snapshot session.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// The bulk of the clean-up code is implemented in Dispose(bool)
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // free managed resources

                //If the perpetuating action isn't set, nothing to do.
                if (PerpetuateAction == null) return;
                //If no need to perpetuate, nothing to do.
                if (!this.IsPersistent) return;

                //If not finished correctly, status is "abend".
                if (!this.FinishTime.HasValue)
                    this.Status = Statuses.Abend;

                //Execute the perpetuating action.
                PerpetuateAction(this);
            }
            // free native resources if there are any.
        }

        #endregion

        #region Subclasses

        #region Statuses
        /// <summary>Represents the status of SnapShot.</summary>
        public enum Statuses : byte
        {
            Undefined,
            Running,
            Abend,
            Finished,
        }
        #endregion

        #endregion
    }
}
